#pragma once

#include<iostream>
#include<string>
#include<list>
#include<memory>
#include<sys/types.h>
#include<sys/socket.h>
#include"InetAddr.hpp"  // 套接字地址
#include"Log.hpp"
#include"Mutex.hpp"

using namespace LogModule;
using namespace LockModule;


// 所有的用户应该有一个公共的方法
class UserInterFace 
{
public:
	virtual ~UserInterFace() = default;
	virtual void SendTo(int sockfd,const std::string& message) = 0;
	virtual bool operator == (const InetAddr& u) = 0;
	virtual std::string Id() = 0;
};


class User : public UserInterFace // 一个用户，用ip区分唯一性
{
public:
	User(const InetAddr& id)
		:_id(id)
	{}
	void SendTo(int sockfd,const std::string& message) override
	{
		LOG(LogLevel::DEBUG) << "send message to" << _id.Addr() << "info: " << message;
		// ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
		
		int n = ::sendto(sockfd,message.c_str(),message.size(),0,_id.NetAddr(),_id.NetAddrLen());
		(void)n;
	}
	bool operator == (const InetAddr& u) override
	{
		return _id == u; // InetAddr的operator==重载，两个User的ip相等即相等
	}
	std::string Id() override
	{
		return _id.Addr();
	}
	~User()
	{}
private:
	InetAddr _id;
};




// 对用户消息进行路由
// UserManger 要把所有的用户先管理起来
// 观察者模式 observer
class UserManger
{
public:
	UserManger()
	{}
	void AddUser(InetAddr& id)
	{
		LockGuard lockguard(_mutex);  //加锁

		for(auto& user : _online_user)
		{
			LOG(LogLevel::INFO) << id.Addr() << "用户已经存在";
			if(*user == id)
				return;
		}
		LOG(LogLevel::INFO) << "新增该用户" << id.Addr();
		_online_user.push_back(std::make_shared<User>(id));
		PrintUser();
	}
	void DelUser(const InetAddr& id)
	{
		// v1
		auto pos = std::remove_if(_online_user.begin(),_online_user.end(),[&id](std::shared_ptr<UserInterFace>& user){
			return *user == id;  // 判断User是否相等，User的operator==重载
		});
		_online_user.erase(pos,_online_user.end());

		PrintUser();
	
		// v2
		// for(auto user : _online_user)
		// {
		// 	if(*user == id)
		// 	{
		// 		_online_user.erase(user);
		// 		break; // 迭代器失效
		// 	}
		// }
	}
	void Router(int sockfd,const std::string& message)  // 消息转发
	{
		LockGuard lockguard(_mutex);

		for(auto& user : _online_user)
		{
			user->SendTo(sockfd,message);
		}
	}

	void PrintUser()
	{
		for(auto user : _online_user)
		{
			LOG(LogLevel::DEBUG) << "在线用户->" << user->Id();
		}
	}
	~UserManger()
	{}
private:
	std::list<std::shared_ptr<UserInterFace>> _online_user; // 在线用户
	Mutex _mutex;
};